#include "Product.h"
#include "debug.h"
#include <pthread.h>
#include <unistd.h>
#include <sys/syscall.h>
#include "misc.h"
#include "logInterface.h"


extern int state15_flag;
extern int state15_err_lck_flag;

typedef struct 
{
    int16_t pf;
    int16_t apparentPwr;
} pwrParam_t;

void Product_EmsInputEmergencyStop()
{
    u16BitType_t state;
    fpagDataFsm_t fsm;

    FuncInf_DirectReadFpga(284, &(state.u16Data));
    printf("[%s][%d] state.u16Data = %d\n", __func__, __LINE__, state.u16Data);
    if(state.bitData.b8)
    {
        printf("干接点输入停机\n");
        FuncInf_GetFsm(FUNCINF_FSM_TYPE_THIS_TIME, &fsm);
        if(fsm != FUNCINF_FSM_IDLE)
        {
            FuncInf_TurnOnOff(FUNCINF_OPERATOR_EMS, NULL, FUNCINF_TURN_OFF);
        }
    }
}

void Product_TransformerStateHandle(void)
{
    u16BitType_t state;
    uint16_t tempU16 = 0;
    int32_t tempI32 = 0;
    static int unlimit_flag = 0;
    static int limit_flag = 0;
    FuncInf_GetTestSwitch(FUNCINF_TEST_SWITCH_TYPE_ALONE_TEST, &tempU16);
    if(tempU16 != 0)
    {
        printf("[%s]: 单机测试使能打开,升压变油温报警不触发", __FUNCTION__);
        return;
    }
    GlobalVariable_GetInt32(GV_INT32_LC_IN_STATE, &tempI32);
    state.u16Data = (uint16_t)tempI32;
    if((state.bitData.b4 == 1) && (limit_flag == 0))
    {
        RatedLimit_SetPercentage(RATED_LIMIT_OWNER_TRANSFORMER_OIL_TEMP_ALARM, 0.9F);
        logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_RATED_LIMIT, 100, COM_DATA_TYPE_NONE, NULL);
        limit_flag = 1;
        unlimit_flag = 0;
        printf("[%s]: 升压变油温报警,PCS功率变额到90%%\n", __FUNCTION__);
    }
    else if((state.bitData.b4 == 0) && (unlimit_flag == 0))
    {
        RatedLimit_SetPercentage(RATED_LIMIT_OWNER_TRANSFORMER_OIL_TEMP_ALARM, 1.0F);
        logInterfaceLogAdd(LOG_CLASS_SPECIAL, LOG_MAINTYPE_RATED_LIMIT, 101, COM_DATA_TYPE_NONE, NULL);
        unlimit_flag = 1;
        limit_flag = 0;
        printf("[%s]: 升压变油温恢复,PCS功率变额到100%%\n", __FUNCTION__);
    }

    GlobalVariable_SetUint8(GV_UINT8_OIL_TEMP, state.bitData.b5);
    GlobalVariable_SetUint8(GV_UINT8_OIL_PRES, state.bitData.b6);
    GlobalVariable_SetUint8(GV_UINT8_OIL_POS, state.bitData.b7);
    GlobalVariable_SetUint8(GV_UINT8_LOAD_BRK, state.bitData.b9);
    GlobalVariable_SetUint8(GV_UINT8_SMOKE, state.bitData.b2);
    GlobalVariable_SetUint8(GV_UINT8_DOOR, state.bitData.b3);
}

void Product_CurZeroUpdate(void)
{
    fpagDataFsm_t fsm;
    float curZeroThr;
    float curAc[3], curDc;

    FuncInf_GetProtectThreshold(FUNCINF_THRSHD_TYPE_CUR_ZERO_BACK, &curZeroThr);
    FuncInf_GetCurrent(FUNCINF_CUR_TYPE_PHASE_A, &curAc[0]);
    FuncInf_GetCurrent(FUNCINF_CUR_TYPE_PHASE_B, &curAc[1]);
    FuncInf_GetCurrent(FUNCINF_CUR_TYPE_PHASE_C, &curAc[2]);
    FuncInf_GetCurrent(FUNCINF_CUR_TYPE_DC, &curDc);

    /* ������ʱ��ȥ������ */
    FuncInf_GetFsm(FUNCINF_FSM_TYPE_THIS_TIME, &fsm);
    printf("curAc[%f][%f][%f] curDc[%f]\n", curAc[0], curAc[1], curAc[2], curDc);
    printf("curZeroThr[%f] fsm[%d]\n", curZeroThr, fsm);
    if(fsm == FUNCINF_FSM_IDLE)
    {
        if(curAc[0] >= curZeroThr)
        {
            GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_AC_A, 1);
        }
        else
        {
            GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_AC_A, 0);
        }

        if(curAc[1] >= curZeroThr)
        {
            GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_AC_B, 1);
        }
        else
        {
            GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_AC_B, 0);
        }

        if(curAc[2] >= curZeroThr)
        {
            GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_AC_C, 1);
        }
        else
        {
            GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_AC_C, 0);
        }

        if(curDc >= curZeroThr)
        {
            GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_DC, 1);
        }
        else
        {
            GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_DC, 0);
        }
    }
    else
    {
        GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_AC_A, 0);
        GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_AC_B, 0);
        GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_AC_C, 0);
        GlobalVariable_SetUint8(GV_UINT8_CUR_ZERO_DC, 0);
    }
}

void Product_OverLeakCur(void)
{
    float ibdCurLeak;
    FuncInf_GetIsoBoardData(FUNCINF_ISO_BOARD_DATA_TYPE_LEAK, &ibdCurLeak);
    float leakCurThr;
    FuncInf_GetArmThrshd(FUNCINF_ARM_THR_TYPE_LEAK_CUR, &leakCurThr);
    printf("[%s][%d] ibdCurLeak = %f leakCurThr = %f\n", __func__, __LINE__, ibdCurLeak, leakCurThr);

    if(ibdCurLeak > (int16_t)leakCurThr * 10)
    {
        GlobalVariable_SetUint8(GV_UINT8_OVER_LEAK_CUR, 1);
    }
    else
    {
        GlobalVariable_SetUint8(GV_UINT8_OVER_LEAK_CUR, 0);
    }
}
/*
    当前削峰填谷策略如下：
        1.满足当前时段执行对应功率；
        2.时段结束（当前时段的最后一秒）执行0功率；
        3.没有任何时段不执行任何操作，保持当前功率。
*/
void Product_PeakLoadShifting(void)
{
    uint16_t testSwitch;
    uint16_t xftgSwitch;
    uint16_t curTime;
    uint16_t curTimeHour;
    uint16_t curTimeMin;
    uint16_t curTimeSec;
    float startTime;
    float endTime;
    float power;
    float curPower;

    FuncInf_GetTestSwitch(FUNCINF_TEST_SWITCH_TYPE_ALONE_TEST, &testSwitch);
    if(testSwitch != 0)
    {
        PRINT_WARN("Test mode opened!!!\n");
        return;
    }
    FuncInf_GetStrategySwitch(FUNCINF_STRTG_SWITCH_TYPE_TIME_PERIOD, &xftgSwitch);
    if(xftgSwitch == 0)
    {
        PRINT_WARN("Time period disabled!!!\n");
        return;
    }

    FuncInf_GetPower(FUNCINF_PWR_TYPE_ACT, &curPower);
    FuncInf_GetTime(FUNCINF_TIME_TYPE_HOUR, &curTimeHour);
    FuncInf_GetTime(FUNCINF_TIME_TYPE_MIN, &curTimeMin);
    FuncInf_GetTime(FUNCINF_TIME_TYPE_SEC, &curTimeSec);
    curTime = curTimeHour * 100 + curTimeMin;
    PRINT_INFO("curPower[%f] curTime[%d] curTimeSec[%d]\n", curPower, curTime, curTimeSec);

    /*Period 1*/
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_BEGIN_1, &startTime);
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_END_1, &endTime);
    startTime = startTime * 100;
    endTime = endTime * 100;
    PRINT_INFO("startTime[%f] endTime[%f]\n", startTime, endTime);
    if(((startTime < endTime) && (curTime >= startTime) && (curTime < endTime))
    ||((startTime > endTime) && (curTime >= startTime) && (curTime >= endTime))
    ||((startTime > endTime) && (curTime < startTime) && (curTime < endTime)))
    {
        FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_POWER_1, &power);
        PRINT_INFO("Period 1 power[%f]\n", power);
        goto Power_execute;
    }
    
    /*Period 2*/
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_BEGIN_2, &startTime);
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_END_2, &endTime);
    startTime = startTime * 100;
    endTime = endTime * 100;
    if(((startTime < endTime) && (curTime >= startTime) && (curTime < endTime))
    ||((startTime > endTime) && (curTime >= startTime) && (curTime >= endTime))
    ||((startTime > endTime) && (curTime < startTime) && (curTime < endTime)))
    {
        FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_POWER_2, &power);
        PRINT_INFO("Period 2 power[%f]\n", power);
        goto Power_execute;
    }

    /*Period 3*/
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_BEGIN_3, &startTime);
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_END_3, &endTime);
    startTime = startTime * 100;
    endTime = endTime * 100;
    if(((startTime < endTime) && (curTime >= startTime) && (curTime < endTime))
    ||((startTime > endTime) && (curTime >= startTime) && (curTime >= endTime))
    ||((startTime > endTime) && (curTime < startTime) && (curTime < endTime)))
    {
        FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_POWER_3, &power);
        PRINT_INFO("Period 3 power[%f]\n", power);
        goto Power_execute;
    }

    /*Period 4*/
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_BEGIN_4, &startTime);
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_END_4, &endTime);
    startTime = startTime * 100;
    endTime = endTime * 100;
    if(((startTime < endTime) && (curTime >= startTime) && (curTime < endTime))
    ||((startTime > endTime) && (curTime >= startTime) && (curTime >= endTime))
    ||((startTime > endTime) && (curTime < startTime) && (curTime < endTime)))
    {
        FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_POWER_4, &power);
        PRINT_INFO("Period 4 power[%f]\n", power);
        goto Power_execute;
    }

    /*Period 5*/
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_BEGIN_5, &startTime);
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_END_5, &endTime);
    startTime = startTime * 100;
    endTime = endTime * 100;
    if(((startTime < endTime) && (curTime >= startTime) && (curTime < endTime))
    ||((startTime > endTime) && (curTime >= startTime) && (curTime >= endTime))
    ||((startTime > endTime) && (curTime < startTime) && (curTime < endTime)))
    {
        FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_POWER_5, &power);
        PRINT_INFO("Period 5 power[%f]\n", power);
        goto Power_execute;
    }

    /*Period 6*/
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_BEGIN_6, &startTime);
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_END_6, &endTime);
    startTime = startTime * 100;
    endTime = endTime * 100;
    if(((startTime < endTime) && (curTime >= startTime) && (curTime < endTime))
    ||((startTime > endTime) && (curTime >= startTime) && (curTime >= endTime))
    ||((startTime > endTime) && (curTime < startTime) && (curTime < endTime)))
    {
        FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_POWER_6, &power);
        PRINT_INFO("Period 6 power[%f]\n", power);
        goto Power_execute;
    }

    /*Period 7*/
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_BEGIN_7, &startTime);
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_END_7, &endTime);
    startTime = startTime * 100;
    endTime = endTime * 100;
    if(((startTime < endTime) && (curTime >= startTime) && (curTime < endTime))
    ||((startTime > endTime) && (curTime >= startTime) && (curTime >= endTime))
    ||((startTime > endTime) && (curTime < startTime) && (curTime < endTime)))
    {
        FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_POWER_7, &power);
        PRINT_INFO("Period 7 power[%f]\n", power);
        goto Power_execute;
    }

    /*Period 8*/
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_BEGIN_8, &startTime);
    FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_END_8, &endTime);
    startTime = startTime * 100;
    endTime = endTime * 100;
    if(((startTime < endTime) && (curTime >= startTime) && (curTime < endTime))
    ||((startTime > endTime) && (curTime >= startTime) && (curTime >= endTime))
    ||((startTime > endTime) && (curTime < startTime) && (curTime < endTime)))
    {
        FuncInf_GetPeriodParam(FUNCINF_PERIOD_PARAM_TYPE_POWER_8, &power);
        PRINT_INFO("Period 8 power[%f]\n", power);
        goto Power_execute;
    }

    PRINT_WARN("No Period!\n");
    return;
Power_execute:
    if((curTime == (endTime - 1)) && (curTimeSec == 59))
    {
        PRINT_INFO("Period Over!Power reset!\n");
        power = 0;
    }
    PRINT_INFO("power[%f] curPower[%f]\n", power, curPower);
    if(FltCmp_IsNotEqual(power, curPower))
    {
        PRINT_INFO("power execute[%f]\n", power);
        FuncInf_SetAppointValue(FUNCINF_OPERATOR_TIME_PERIOD, FUNCINF_APPOINT_TYPE_ACT_PWR, power);
    }
}

void Product_Thread(void* pPara)
{   
    Misc_InitThread(__func__);

    while(1)
    {
        // printf("Product_Thread is running...\n");

        // Product_EmsInputEmergencyStop();

        Product_TransformerStateHandle();

        Product_CurZeroUpdate();

        Product_OverLeakCur();

        Product_PeakLoadShifting();

        usleep(1000000);
    }
}
